home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_066 / malloctest / mtest.c next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  433 lines

  1. #include <stdio.h>
  2.  
  3. extern int      atoi ();
  4. extern int      rand ();
  5. extern char    *sbrk ();
  6.  
  7. extern char    *malloc ();
  8. extern char    *realloc ();
  9. extern int      free ();
  10.  
  11. struct memevent {
  12.         int                     m_time;         /* time to go */
  13.         char                   *m_memory;       /* malloc'ed mem */
  14.         unsigned                m_size;         /* size of mem */
  15.         int                     m_id;           /* id, for trace/debug */
  16.         int                     m_realloc;      /* counter, for debugging */
  17.         char                    m_pattern;      /* pattern in memory */
  18.         struct memevent        *m_next;         /* linked list pointer */
  19. };
  20.  
  21. #ifndef MAX_EVENTS
  22. #define MAX_EVENTS      10000
  23. #endif
  24.  
  25. struct memevent eventpool[ MAX_EVENTS ];
  26.  
  27. struct memevent *events;
  28. struct memevent *free_events;
  29.  
  30. char stdout_buf[ BUFSIZ ];
  31. char stderr_buf[ BUFSIZ ];
  32.  
  33. int time_to_go;
  34. int new_probability;
  35. int realloc_probability = 25;           /* XXX: should set from argv */
  36. int stat_frequency;
  37.  
  38. main (argc, argv)
  39. int argc;
  40. char *argv[];
  41. {
  42.         init (argc, argv);
  43.         run_test ();
  44. }
  45.  
  46. /*
  47.  * run_test ()
  48.  *
  49.  * Run the actual memory test.
  50.  */
  51.  
  52. run_test ()
  53. {
  54.         while (time_to_go > 0) {
  55.                 arrival ();
  56.                 service ();
  57.                 -- time_to_go;
  58.                 if ((time_to_go % stat_frequency) == 0)
  59.                         do_stats ();
  60.         }
  61. }
  62.  
  63. /*
  64.  * arrival ()
  65.  *
  66.  * With probability new_probability/100, allocate a new piece
  67.  * of memory with some randomly determined size and lifetime,
  68.  * and add it to the memory event list.
  69.  */
  70.  
  71. arrival ()
  72. {
  73.         if (free_events && odds (new_probability, 100)) {
  74.                 register struct memevent *m;
  75.                 register char *p;
  76.  
  77.                 m = free_events;
  78.                 free_events = m->m_next;
  79.                 m->m_next = NULL;
  80.  
  81.                                         /* XXX: let these be set from argv */
  82.                 m->m_size = (unsigned) random_range (1, 100);
  83.                 if (time_to_go < 100)
  84.                         m->m_time = random_range (1, time_to_go);
  85.                 else
  86.                         m->m_time = random_range (1, 100);
  87.  
  88.                 m->m_pattern = (char) random_range (0, 127);
  89.                 m->m_realloc = 0;
  90.                 m->m_memory = malloc (m->m_size);
  91.                 if (! m->m_memory)
  92.                         out_of_memory ();
  93.  
  94.  
  95.                 for (p = m->m_memory; p < & m->m_memory[ m->m_size ]; p++)
  96.                         *p = m->m_pattern;
  97.  
  98.                 add_to_events (m);
  99.         }
  100. } /* arrival */
  101.  
  102. /*
  103.  * do_stats ()
  104.  */
  105.  
  106. do_stats ()
  107. {
  108.         register struct memevent *m;
  109.         int i;
  110.         long total;
  111.  
  112.         printf ("---------------------\nTIME Remaining: %d\n", time_to_go);
  113.  
  114.         /* print other interesting but implementation-dependent stuff here
  115.            (like count of blocks in heap, size of heap, etc) */
  116.  
  117.         total = 0;
  118.         for (i = 1, m = events; m != NULL; m = m->m_next, i++) {
  119.                 printf ("EVENT %5d (id %5d): ", i, m->m_id);
  120.                 printf ("SIZE %4d, ", m->m_size);
  121.                 printf ("PATTERN 0x%02x, ", m->m_pattern & 0xFF);
  122.                 printf ("TIME %4d ", m->m_time);
  123.                 if (m->m_realloc > 0)
  124.                         printf ("REALLOC %d", m->m_realloc);
  125.                 printf ("\n");
  126.                 total += m->m_size;
  127.         }
  128.         printf ("TOTAL events %d, allocated memory %d\n", i-1, total);
  129.         (void) fflush (stdout);
  130. } /* do_stats */
  131.  
  132. /*
  133.  * service ()
  134.  *
  135.  * Decrement the time remaining on the head event.  If
  136.  * it's time is up (zero), service it.
  137.  *
  138.  * Servicing an event generally means free'ing it (after checking
  139.  * for corruption).  It is also possible (realloc_probability) to
  140.  * realloc the event instead.
  141.  */
  142.  
  143. service ()
  144. {
  145.         register struct memevent *m;
  146.  
  147.         if ((m = events) != NULL)
  148.                 -- m->m_time;
  149.  
  150.         while (m != NULL && m->m_time == 0) {
  151.                 register char *p;
  152.  
  153.                 for (p = m->m_memory; p < & m->m_memory[ m->m_size ]; p++) {
  154.                         if (*p != m->m_pattern)
  155.                                 corrupted ();
  156.                 }
  157.  
  158.                 events = m->m_next;     /* delete this event */
  159.  
  160.                 if (time_to_go > 1 && odds (realloc_probability, 100))
  161.                         realloc_event (m);
  162.                 else
  163.                         free_event (m);
  164.  
  165.                 m = events;
  166.  
  167.         }
  168. } /* service */
  169.  
  170. /*
  171.  * free_event (m)
  172.  *
  173.  * Called to free up the given event, including its memory.
  174.  */
  175.  
  176. free_event (m)
  177. register struct memevent *m;
  178. {
  179.         free (m->m_memory);
  180.         m->m_next = free_events;
  181.         free_events = m;
  182. }
  183.  
  184. /*
  185.  * realloc_event (m)
  186.  *
  187.  * Called from service(), to reallocate an event's memory,
  188.  * rather than freeing it.
  189.  */
  190.  
  191. realloc_event (m)
  192. register struct memevent *m;
  193. {
  194.         register char *p;
  195.         unsigned new_size;
  196.         unsigned min_size;
  197.  
  198.                                         /* XXX: let these be set from argv */
  199.         new_size = (unsigned) random_range (1, 100);
  200.  
  201.         ++ m->m_realloc;                /* for stats */
  202.         m->m_memory = realloc (m->m_memory, new_size);
  203.         if (! m->m_memory)
  204.                 out_of_memory ();
  205.  
  206.         m->m_next = NULL;
  207.  
  208.         if (time_to_go < 100)
  209.                 m->m_time = random_range (1, time_to_go - 1);
  210.         else
  211.                 m->m_time = random_range (1, 100);   /* XXX: should set from argv */
  212.  
  213.         min_size = new_size > m->m_size ? m->m_size : new_size;
  214.  
  215.         for (p = m->m_memory; p < & m->m_memory[ min_size ]; p++) {
  216.                 if (*p != m->m_pattern)
  217.                         corrupted ();
  218.         }
  219.  
  220.         m->m_size = new_size;
  221.         for (p = m->m_memory; p < & m->m_memory[ m->m_size ]; p++)
  222.                 *p = m->m_pattern;
  223.  
  224.  
  225.         add_to_events (m);
  226. } /* realloc_event */
  227.  
  228. /*
  229.  * add_to_events (m)
  230.  *
  231.  * Add the given event structure onto the time-ordered event list.
  232.  */
  233.  
  234. add_to_events (m)
  235. register struct memevent *m;
  236. {
  237.         register struct memevent *l;
  238.         register struct memevent *ol;
  239.  
  240.         for (ol = NULL, l = events; l != NULL; ol = l, l = l->m_next) {
  241.                 if (l->m_time > m->m_time) {
  242.                         if (ol == NULL) {
  243.                                 m->m_next = events;
  244.                                 events = m;
  245.                         }
  246.                         else {
  247.                                 m->m_next = l;
  248.                                 ol->m_next = m;
  249.                         }
  250.  
  251.                         l->m_time -= m->m_time;
  252.                         return;
  253.                 }
  254.  
  255.                 m->m_time -= l->m_time;
  256.         }
  257.  
  258.         if (events == NULL)
  259.                 events = m;
  260.         else
  261.                 ol->m_next = m;
  262. } /* add_to_events */
  263.  
  264. /*
  265.  * init_events ()
  266.  *
  267.  * Set up the memevent pools.
  268.  */
  269.  
  270. init_events ()
  271. {
  272.         register struct memevent *m;
  273.         int i;
  274.  
  275.         for (i = 0, m = eventpool; m < & eventpool[ MAX_EVENTS ]; m++, i++) {
  276.                 m->m_id = i;
  277.                 m->m_next = m + 1;
  278.         }
  279.  
  280.         eventpool[ MAX_EVENTS-1 ].m_next = NULL;
  281.  
  282.         free_events = eventpool;
  283. }
  284.  
  285. /*
  286.  * init (argc, argv)
  287.  *
  288.  * Initialize the memory tests.
  289.  */
  290.  
  291. init (argc, argv)
  292. int argc;
  293. char *argv[];
  294. {
  295.     if (argc != 4) {
  296.         fprintf (stderr, "usage: %s new_prob time_to_go stat_freq\n", argv[ 0 ]);
  297.         exit (1);
  298.     }
  299.         new_probability = atoi (argv[ 1 ]);
  300.         time_to_go = atoi (argv[ 2 ]);
  301.         stat_frequency = atoi (argv[ 3 ]);
  302.  
  303.         srand (1);
  304.  
  305.         init_events ();
  306.  
  307.         /*
  308.          * Use statically allocated buffers, otherwise
  309.          * stdio() will call malloc to allocate buffers, and
  310.          * this gets confusing when debugging stuff.
  311.          */
  312.  
  313.         setbuf (stdout, stdout_buf);
  314.         setbuf (stderr, stderr_buf);
  315. }
  316.  
  317. /*
  318.  * XXX: Should really send SIGQUIT ...
  319.  */
  320.  
  321. cause_core_dump ()
  322. {
  323.         * (long *) 1 = 5;
  324. }
  325.  
  326. corrupted ()
  327. {
  328.         printf ("Corrupted\n");
  329.         cause_core_dump ();
  330. }
  331.  
  332. out_of_memory ()
  333. {
  334.         printf ("Out of memory!\n");
  335.         cause_core_dump ();
  336. }
  337.  
  338. /*
  339.  * odds (m, n)
  340.  *
  341.  * Return TRUE (non-zero) with probability m out of n.
  342.  */
  343.  
  344. odds (m, n)
  345. int m;
  346. int n;
  347. {
  348.         return ((rand () % n) < m);
  349. }
  350.  
  351. /*
  352.  * random_range (lo, hi)
  353.  *
  354.  * Pick a random integer from lo to hi (inclusive).
  355.  */
  356.  
  357. random_range (lo, hi)
  358. int lo;
  359. int hi;
  360. {
  361.         return ((rand () % (hi - lo + 1)) + lo);
  362. }
  363.  
  364. #if DBG
  365. /*
  366.  * de_cmpf (m1,m2)
  367.  *
  368.  * compare function for qsort() in dump_events.
  369.  * Sort by memory address of the memory allocated to
  370.  * the event.
  371.  */
  372.  
  373. int
  374. de_cmpf (m1, m2)
  375. struct memevent **m1;
  376. struct memevent **m2;
  377. {
  378.         unsigned long maddr1 = (unsigned long) (*m1)->m_memory;
  379.         unsigned long maddr2 = (unsigned long) (*m2)->m_memory;
  380.  
  381.                                         /* sloppy */
  382.         return (maddr1 - maddr2);
  383. }
  384. #endif DBG
  385.  
  386. /*
  387.  * dump_events ()
  388.  *
  389.  * Useful for debugging.
  390.  */
  391.  
  392. #if DBG
  393. dump_events ()
  394. {
  395.         static struct memevent *sorted[ MAX_EVENTS ];
  396.         register struct memevent *m;
  397.         register int i;
  398.  
  399.         fprintf (stderr, "DUMP EVENTS (time remaining = %d)\n", time_to_go);
  400.  
  401.         for (m = events, i = 0; m != NULL; m = m->m_next, i++)
  402.                 sorted[ i ] = m;
  403.  
  404.         if (i == 0) {
  405.                 fprintf (stderr, "No events.\n");
  406.                 return;
  407.         }
  408.  
  409.         qsort ((char *) sorted, i, sizeof (struct memevent *), de_cmpf);
  410.  
  411.         sorted[ i ] = 0;
  412.         for (i = 0, m = sorted[ 0 ]; m != NULL; m = sorted[ ++i ]) {
  413.                 fprintf (stderr, "E# %3d: ", m->m_id);
  414.                 fprintf (stderr, "SIZ%4d, ", m->m_size);
  415.                 fprintf (stderr, "RANGE: 0x%08x -- 0x%08x ",
  416.                                 m->m_memory, m->m_memory + m->m_size - 1);
  417.                 (void) fflush (stderr);
  418.  
  419.                                         /* Peek at the surrounding longs,
  420.                                            for debugging a particular malloc
  421.                                            implementation.  Your choices may
  422.                                            vary. */
  423.  
  424.                 fprintf (stderr, "BOUNDARY TAGS: %4d ", * (long *) (m->m_memory - 4));
  425.                 (void) fflush (stderr);
  426.                 fprintf (stderr, "%4d\n", * (long *) ((m->m_memory - 8) - (* (long *) (m->m_memory - 4))));
  427.                 (void) fflush (stderr);
  428.         }
  429.         fprintf (stderr, "END DUMP_EVENTS\n");
  430.         (void) fflush (stderr);
  431. } /* dump_events */
  432. #endif DBG
  433.